/*
 * client_connection.cpp
 *
 *  Created on: 2012-4-1
 *      Author: lixingyi
 */
#include <stdlib.h>
#include <string.h>

#include "client_connection.h"

#include "client_application.h"
#include "base_packet.h"
#include "knet_messagebody_gameserver.h"
#include "knet_messagebody_gameserver_noti.h"


#include <iostream>
#include <string>
using namespace std;

typedef cs_packet<MSGID_GS_REQ_GET_HOSTLIST,CGSGetHostListReq> get_host_list_request ;
typedef cs_packet<MSGID_GS_RESP_GET_HOSTLIST,CGSGetHostListResp> get_host_list_response;

typedef cs_packet<MSGID_GS_REQ_LOGIN,CGSLoginReq> player_login_request ;
typedef cs_packet<MSGID_GS_RESP_LOGIN,CGSLoginResp> player_login_response ;

typedef cs_packet<MSGID_GS_REQ_CREATEROLE,CGSCreateRoleReq> create_player_request;
typedef cs_packet<MSGID_GS_RESP_CREATEROLE,CGSCreateRoleResp> create_player_response;


typedef cs_packet<MSGID_GS_REQ_HEARTBEAT,CGSHeartBeatReq> heartbeat_request ;
typedef cs_packet<MSGID_GS_RESP_HEARTBEAT,CGSHeartBeatResp> heartbeat_response ;


typedef cs_packet<MSGID_GS_REQ_UPDATECITYCOOR,CGSUpdateCityCoorReq> move_request ;
//typedef cs_packet<MSGID_GS_RESP_UPDATECITYCOOR,CGSUpdateCityCoorResp> move_response ;

typedef cs_packet<MSGID_GS_REQ_EXCHANGE_CDKEY,CGSExchangeCDKEYReq> cdkey_request ;
typedef cs_packet<MSGID_GS_RESP_EXCHANGE_CDKEY,CGSExchangeCDKEYResp> cdkey_response ;


//sync pos 
typedef cs_packet<MSGID_NOTI_SYNCROLE,CGSSyncRoleNoti> move_notify ;

client_connection::client_connection():m_uid(0),
    m_count(0),m_seq(0),
	m_status(STATUS_ACC_LOGIN)
	
{
    m_timer.set_owner(this) ;

}

client_connection::~client_connection()
{
    // TODO Auto-generated destructor stub
    fini();
}


void client_connection::run(int uid,int delay_ms,const char* name)
{
    m_uid = uid ;
    m_role_id = -1 ;
    if( name != NULL )
    {
        strncpy(m_name,name,sizeof(m_name)) ;
    }
    else
    {
        snprintf(m_name,sizeof(m_name),"player%d",m_uid) ;
    }
    m_delt_x = 7 ;
    m_delt_y =8 ;
    m_count = 0 ;
    m_status =STATUS_ACC_LOGIN ;
    m_seq = 0 ;
    m_run_time = time(0) ;

    //should login in 5s  else close the connection
    get_app().add_timer(&m_timer,5000) ;

}

void client_connection::on_connected()
{
    info_log_format(get_app().logger,"client on_connected ,name:%s\n",m_name);
    send_acc_login();
    //send_heartbeat();
}

void client_connection::on_closed(int type,int no)
{
    info_log_format(get_app().logger,
        "client on_closed:%d errno:%d name:%s\n",type,no,m_name) ;



}
int client_connection::get_packet_info(const char* data,int size,packet_info* pi)
{

    if(size < (int)sizeof(cs_head) )
    {
        pi->size = (int)sizeof(cs_head) ;
    }
    else
    {
        cs_head* head = (cs_head*)data ;
        pi->type = ntoh_int16(head->msg_id) ;
        pi->size = ntoh_int32(head->length) ;
        pi->data = data ;
    }

    debug_log_format(get_app().logger,
        "client recv type:%#x size:%d real_size:%d\n",pi->type,pi->size,size) ;

    return 0 ;
}
int client_connection::process_packet(const packet_info* pi)
{
    
    switch(pi->type)
    {
    case get_host_list_response::packet_type:
        if(m_status == STATUS_ACC_LOGIN) return process_acc_login_response(pi) ;
        break ;
    case player_login_response::packet_type:
        if(m_status == STATUS_PLAYER_LOGIN) return process_player_login_response(pi) ;
        break ;
    case create_player_response::packet_type:
        if(m_status == STATUS_CREATE_PLAYER) return process_create_player_response(pi) ;
        break ;

    case move_notify::packet_type:
        if(m_status == STATUS_IN_GAME) return process_move_notify(pi);
    case cdkey_response::packet_type:
        if(m_status == STATUS_IN_GAME) return process_cdkey_response(pi);
    default:
        return process_game_packet_response(pi) ;
    }
    
        
    return -1 ;
}

int client_connection::process_move_notify(const packet_info* pi)
{
    move_notify response ;
    if(response.decode(pi->data,pi->size)!=pi->size) return -1 ;
    vector<SyncRole>::iterator it ;
    for(it=response.body.vSyncRole.begin();it!=response.body.vSyncRole.end();++it)
    {
        debug_log_format(get_app().logger,
            "move_notify:%s (%d,%d)\n",it->szName,it->nX,it->nY) ;
    }
    
    return 0 ;

}

int client_connection::process_cdkey_response(const packet_info* pi)
{
    cdkey_response response ;
    if(response.decode(pi->data,pi->size)!=pi->size) return -1 ;
    info_log_format(get_app().logger,"code:%d",response.body.nErrorCode) ;
    
    return 0 ;

}


int client_connection::process_acc_login_response(const packet_info* pi)
{
    get_host_list_response response ;
    if(response.decode(pi->data,pi->size)!=pi->size) return -1 ;
    info_log_format(get_app().logger,
        "acc_login_response:%d\n",response.body.nErrorCode) ;
    
    
    if(response.body.vLoginBaseinfo.empty() )
    {
        //create
        send_create_player() ;
    }
    else
    {
        VHostLoginBaseInfo::iterator it = response.body.vLoginBaseinfo.begin();
        //printf("role_id:%d\n",it->nRoleID);
        m_role_id = it->nRoleID ;
        //login
        send_player_login() ;
    }
    return 0 ;
}




int client_connection::process_create_player_response(const packet_info* pi)
{
    create_player_response response ;
    if(response.decode(pi->data,pi->size)!=pi->size) return -1 ;
    info_log_format(get_app().logger,
        "create_player role_id:%d result:%d\n",response.body.nRoleID,response.body.nCreateResult) ;

    if(response.body.nCreateResult == 0 )
    {
        m_role_id = response.body.nRoleID;
        send_player_login() ;
    }
    return 0 ;
}

int client_connection::process_player_login_response(const packet_info* pi)
{
    player_login_response response ;
    if(response.decode(pi->data,pi->size)!=pi->size) return -1 ;
    
    info_log_format(get_app().logger,
        "player_login_response:%#x pos(%d,%d))\n",
        response.body.nErrorCode,
        response.body.nX,
        response.body.nY ) ;
    
    if(response.body.nX < 1000) m_delt_x = response.body.nX ;
    if(response.body.nY < 1000) m_delt_y = response.body.nY ;
    
    m_status = STATUS_IN_GAME ;

    return 0 ;
}

int client_connection::process_game_packet_response(const packet_info* pi)
{
    

    

    return 0 ;
}


void client_connection::send_create_player()
{

    create_player_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq() ;

    
    request.body.nRoleID = m_role_id ;
    request.body.nSoldierID = 80001 + rand() % 4 ;
    strcpy(request.body.szAccountID,m_name);
    strcpy(request.body.szRoleName,m_name);
	strcpy(request.body.szPasswd,"123456");
        
    send(&request,0) ;
    m_status = STATUS_CREATE_PLAYER ;
    //printf("send_create_player\n");
} 
void client_connection::send_acc_login()
{

    get_host_list_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq();
    
    request.body.nRoleID = m_role_id ;
    strcpy(request.body.szAccount,m_name);
   
    
    send(&request,0) ;
    m_status = STATUS_ACC_LOGIN ;

    //printf("send_acc_login name:%s\n",m_name);
} 



void client_connection::send_heartbeat()
{
    heartbeat_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq();

    

    request.body.nRoleID = m_role_id ;
    send(&request,0) ;
    m_heart_time = time(0) ;
    //printf("send_heartbeat\n");
    
} 

void client_connection::send_cdkey()
{
    cdkey_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq();

    

    request.body.nRoleID = m_role_id ;
    strcpy(request.body.szCDKEY,"test") ;
    send(&request,0) ;
   
    
} 


void client_connection::send_move()
{
    move_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq();



    request.body.nRoleID = m_role_id ;
    
    request.body.nX = m_delt_x ;
    request.body.nY = m_delt_y ;
    send(&request,0) ;

    debug_log_format(get_app().logger,
        "send_move pos(%d,%d)\n",m_delt_x,m_delt_y);
    
} 


void client_connection::send_player_login()
{
    player_login_request request ;
    request.head.role_id = m_role_id ;
    request.head.seq = generate_seq() ;

    request.body.nRoleID = m_role_id ;
    request.body.sziOpenID[0] = '\0';
    request.body.szVia1[0] = '\0';
    request.body.szVia2[0] = '\0';
    send(&request,0) ;
    m_status = STATUS_PLAYER_LOGIN ;
    //printf("send_player_login\n");
}


void client_connection::on_timeout(timer_manager* manager)
{
        
    //printf("client timer status:%d\n",m_status) ;
    

    if(m_status == STATUS_IN_GAME && (time(0) - m_run_time< 3600) )
    {
        start_move_timer() ;
        
        if(time(0) - m_heart_time > 60 ) send_heartbeat() ;
        
    }
    else
    {
        fini();
    }


    

}


int client_connection::start_move_timer()
{

/*
    int delt_array[3] = { 0 ,1 ,-1} ;
    int x = 0 , y = 0 ; 
    do
    {
        x = delt_array[rand()% 3] ;
        y = delt_array[rand()% 3] ;
    }while( (x==0) && (y==0) );

    m_count = rand() % 5 + 2 ;
    //move to new position relative to old position
    m_delt_x = x*m_count ;
    m_delt_y = y*m_count ;
*/    
    //get_app().generate_pos(&m_delt_x,&m_delt_y);

    //send_move();
    send_cdkey() ;

    if(get_app().add_timer(&m_timer,1000* (rand()%20+10) )!=0) return -1;
    
    return 0 ;
      
}

/*

int client_connection::start_teleport_timer(timer_manager* manager)
{

    send_teleport() ;
    m_timer.set_expired(get_app().get_run_ms() + 5000 ) ;
    if(manager->add_timer(&m_timer)!=0) return -1;

    return 0 ;
    
}


int client_connection::start_login_timer(timer_manager* manager)
{

    send_acc_login() ;
    m_timer.set_expired(get_app().get_run_ms() + 5000 ) ;
    if(manager->add_timer(&m_timer)!=0) return -1;

    return 0 ;
    
}


int client_connection::start_talk_timer(timer_manager* manager)
{

    send_talk_channel() ;
    m_timer.set_expired(get_app().get_run_ms() + 1000 ) ;
    if(manager->add_timer(&m_timer)!=0) return -1;

    return 0 ;
    
}
*/

